home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / emacs-complete / fsf / emacs / lwlib / lwlib.c < prev    next >
C/C++ Source or Header  |  1994-05-24  |  30KB  |  1,298 lines

  1. /* A general interface to the widgets of different toolkits.
  2.    Copyright (C) 1992, 1993 Lucid, Inc.
  3.  
  4. This file is part of the Lucid Widget Library.
  5.  
  6. The Lucid Widget Library is free software; you can redistribute it and/or 
  7. modify it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. The Lucid Widget Library is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #ifdef NeXT
  21. #undef __STRICT_BSD__ /* ick */
  22. #endif
  23.  
  24. #include <sys/types.h>
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include "lwlib-int.h"
  28. #include "lwlib-utils.h"
  29. #include <X11/StringDefs.h>
  30.  
  31. #if defined (USE_LUCID)
  32. #include "lwlib-Xlw.h"
  33. #endif
  34. #if defined (USE_MOTIF)
  35. #include "lwlib-Xm.h"
  36. #else /* not USE_MOTIF */
  37. #if defined (USE_LUCID)
  38. #define USE_XAW
  39. #endif /* not USE_MOTIF && USE_LUCID */
  40. #endif
  41. #if defined (USE_OLIT)
  42. #include "lwlib-Xol.h"
  43. #endif
  44. #if defined (USE_XAW)
  45. #include "lwlib-Xaw.h"
  46. #endif
  47.  
  48. #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
  49. ERROR!  At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
  50. #endif
  51.  
  52. #if defined (USE_MOTIF) && defined (USE_OLIT)
  53. ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
  54. #endif
  55.  
  56. #ifndef max
  57. #define max(x, y) ((x) > (y) ? (x) : (y))
  58. #endif
  59.  
  60. /* List of all widgets managed by the library. */
  61. static widget_info*
  62. all_widget_info = NULL;
  63.  
  64. /* Forward declarations */
  65. static void
  66. instanciate_widget_instance (/* widget_instance* instance */);
  67.  
  68. lwlib_memset (address, value, length)
  69.      char *address;
  70.      int value;
  71.      int length;
  72. {
  73.   int i;
  74.  
  75.   for (i = 0; i < length; i++)
  76.     address[i] = value;
  77. }
  78.  
  79. lwlib_bcopy (from, to, length)
  80.      char *from;
  81.      char *to;
  82.      int length;
  83. {
  84.   int i;
  85.  
  86.   for (i = 0; i < length; i++)
  87.     to[i] = from[i];
  88. }
  89. /* utility functions for widget_instance and widget_info */
  90. char *
  91. safe_strdup (s)
  92.      char *s;
  93. {
  94.   char *result;
  95.   if (! s) return 0;
  96.   result = (char *) malloc (strlen (s) + 1);
  97.   if (! result)
  98.     return 0;
  99.   strcpy (result, s);
  100.   return result;
  101. }
  102.  
  103. /* Like strcmp but ignore differences in case.  */
  104.  
  105. static int
  106. my_strcasecmp (s1, s2)
  107.      char *s1, *s2;
  108. {
  109.   while (1)
  110.     {
  111.       int c1 = *s1++;
  112.       int c2 = *s2++;
  113.       if (isupper (c1))
  114.     c1 = tolower (c1);
  115.       if (isupper (c2))
  116.     c2 = tolower (c2);
  117.       if (c1 != c2)
  118.     return (c1 > c2 ? 1 : -1);
  119.       if (c1 == 0)
  120.     return 0;
  121.     }
  122. }
  123.  
  124. static void
  125. safe_free_str (s)
  126.      char *s;
  127. {
  128.   if (s) free (s);
  129. }
  130.  
  131. static widget_value *widget_value_free_list = 0;
  132. static int malloc_cpt = 0;
  133.  
  134. widget_value *
  135. malloc_widget_value ()
  136. {
  137.   widget_value *wv;
  138.   if (widget_value_free_list)
  139.     {
  140.       wv = widget_value_free_list;
  141.       widget_value_free_list = wv->free_list;
  142.       wv->free_list = 0;
  143.     }
  144.   else
  145.     {
  146.       wv = (widget_value *) malloc (sizeof (widget_value));
  147.       malloc_cpt++;
  148.     }
  149.   lwlib_memset (wv, 0, sizeof (widget_value));
  150.   return wv;
  151. }
  152.  
  153. /* this is analagous to free().  It frees only what was allocated
  154.    by malloc_widget_value(), and no substructures. 
  155.  */
  156. void
  157. free_widget_value (wv)
  158.      widget_value *wv;
  159. {
  160.   if (wv->free_list)
  161.     abort ();
  162.  
  163.   if (malloc_cpt > 25)
  164.     {
  165.       /* When the number of already allocated cells is too big,
  166.      We free it.  */
  167.       free (wv);
  168.       malloc_cpt--;
  169.     }
  170.   else
  171.     {
  172.       wv->free_list = widget_value_free_list;
  173.       widget_value_free_list = wv;
  174.     }
  175. }
  176.  
  177. static void
  178. free_widget_value_tree (wv)
  179.      widget_value *wv;
  180. {
  181.   if (!wv)
  182.     return;
  183.  
  184.   if (wv->name) free (wv->name);
  185.   if (wv->value) free (wv->value);
  186.   if (wv->key) free (wv->key);
  187.  
  188.   wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
  189.  
  190.   if (wv->toolkit_data && wv->free_toolkit_data)
  191.     {
  192.       free (wv->toolkit_data);
  193.       wv->toolkit_data = (void *) 0xDEADBEEF;
  194.     }
  195.  
  196.   if (wv->contents && (wv->contents != (widget_value*)1))
  197.     {
  198.       free_widget_value_tree (wv->contents);
  199.       wv->contents = (widget_value *) 0xDEADBEEF;
  200.     }
  201.   if (wv->next)
  202.     {
  203.       free_widget_value_tree (wv->next);
  204.       wv->next = (widget_value *) 0xDEADBEEF;
  205.     }
  206.   free_widget_value (wv);
  207. }
  208.  
  209. static widget_value *
  210. copy_widget_value_tree (val, change)
  211.      widget_value* val;
  212.      change_type change;
  213. {
  214.   widget_value* copy;
  215.   
  216.   if (!val)
  217.     return NULL;
  218.   if (val == (widget_value *) 1)
  219.     return val;
  220.  
  221.   copy = malloc_widget_value ();
  222.   copy->name = safe_strdup (val->name);
  223.   copy->value = safe_strdup (val->value);
  224.   copy->key = safe_strdup (val->key);
  225.   copy->enabled = val->enabled;
  226.   copy->selected = val->selected;
  227.   copy->edited = False;
  228.   copy->change = change;
  229.   copy->contents = copy_widget_value_tree (val->contents, change);
  230.   copy->call_data = val->call_data;
  231.   copy->next = copy_widget_value_tree (val->next, change);
  232.   copy->toolkit_data = NULL;
  233.   copy->free_toolkit_data = False;
  234.   return copy;
  235. }
  236.  
  237. static widget_info *
  238. allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
  239.      char* type;
  240.      char* name;
  241.      LWLIB_ID id;
  242.      widget_value* val;
  243.      lw_callback pre_activate_cb;
  244.      lw_callback selection_cb;
  245.      lw_callback post_activate_cb;
  246. {
  247.   widget_info* info = (widget_info*)malloc (sizeof (widget_info));
  248.   info->type = safe_strdup (type);
  249.   info->name = safe_strdup (name);
  250.   info->id = id;
  251.   info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
  252.   info->busy = False;
  253.   info->pre_activate_cb = pre_activate_cb;
  254.   info->selection_cb = selection_cb;
  255.   info->post_activate_cb = post_activate_cb;
  256.   info->instances = NULL;
  257.  
  258.   info->next = all_widget_info;
  259.   all_widget_info = info;
  260.  
  261.   return info;
  262. }
  263.  
  264. static void
  265. free_widget_info (info)
  266.      widget_info* info;
  267. {
  268.   safe_free_str (info->type);
  269.   safe_free_str (info->name);
  270.   free_widget_value_tree (info->val);
  271.   lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
  272.   free (info);
  273. }
  274.  
  275. static void
  276. mark_widget_destroyed (widget, closure, call_data)
  277.      Widget widget;
  278.      XtPointer closure;
  279.      XtPointer call_data;
  280. {
  281.   widget_instance* instance = (widget_instance*)closure;
  282.  
  283.   /* be very conservative */
  284.   if (instance->widget == widget)
  285.     instance->widget = NULL;
  286. }
  287.  
  288. static widget_instance *
  289. allocate_widget_instance (info, parent, pop_up_p)
  290.      widget_info* info;
  291.      Widget parent;
  292.      Boolean pop_up_p;
  293. {
  294.   widget_instance* instance =
  295.     (widget_instance*)malloc (sizeof (widget_instance));
  296.   instance->parent = parent;
  297.   instance->pop_up_p = pop_up_p;
  298.   instance->info = info;
  299.   instance->next = info->instances;
  300.   info->instances = instance;
  301.  
  302.   instanciate_widget_instance (instance);
  303.  
  304.   XtAddCallback (instance->widget, XtNdestroyCallback,
  305.          mark_widget_destroyed, (XtPointer)instance);
  306.   return instance;
  307. }
  308.  
  309. static void
  310. free_widget_instance (instance)
  311.      widget_instance* instance;
  312. {
  313.   lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
  314.   free (instance);
  315. }
  316.  
  317. static widget_info *
  318. get_widget_info (id, remove_p)
  319.      LWLIB_ID id;
  320.      Boolean remove_p;
  321. {
  322.   widget_info* info;
  323.   widget_info* prev;
  324.   for (prev = NULL, info = all_widget_info;
  325.        info;
  326.        prev = info, info = info->next)
  327.     if (info->id == id)
  328.      {
  329.        if (remove_p)
  330.      {
  331.        if (prev)
  332.          prev->next = info->next;
  333.        else
  334.          all_widget_info = info->next;
  335.      }
  336.       return info;
  337.      }
  338.   return NULL;
  339. }
  340.  
  341. /* Internal function used by the library dependent implementation to get the
  342.    widget_value for a given widget in an instance */
  343. widget_info *
  344. lw_get_widget_info (id)
  345.      LWLIB_ID id;
  346. {
  347.   return get_widget_info (id, 0);
  348. }
  349.  
  350. static widget_instance *
  351. get_widget_instance (widget, remove_p)
  352.      Widget widget;
  353.      Boolean remove_p;
  354. {
  355.   widget_info* info;
  356.   widget_instance* instance;
  357.   widget_instance* prev;
  358.   for (info = all_widget_info; info; info = info->next)
  359.     for (prev = NULL, instance = info->instances;
  360.      instance;
  361.      prev = instance, instance = instance->next)
  362.       if (instance->widget == widget)
  363.     {
  364.       if (remove_p)
  365.         {
  366.           if (prev)
  367.         prev->next = instance->next;
  368.           else
  369.         info->instances = instance->next;
  370.         }
  371.       return instance;
  372.     }
  373.   return (widget_instance *) 0;
  374. }
  375.  
  376. static widget_instance*
  377. find_instance (id, parent, pop_up_p)
  378.      LWLIB_ID id;
  379.      Widget parent;
  380.      Boolean pop_up_p;
  381. {
  382.   widget_info* info = get_widget_info (id, False);
  383.   widget_instance* instance;
  384.  
  385.   if (info)
  386.     for (instance = info->instances; instance; instance = instance->next)
  387.       if (instance->parent == parent && instance->pop_up_p == pop_up_p)
  388.     return instance;
  389.  
  390.   return NULL;
  391. }
  392.  
  393.  
  394. /* utility function for widget_value */
  395. static Boolean
  396. safe_strcmp (s1, s2)
  397.      char* s1;
  398.      char* s2;
  399. {
  400.   if (!!s1 ^ !!s2) return True;
  401.   return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
  402. }
  403.  
  404.  
  405. #if 0
  406. # define EXPLAIN(name, oc, nc, desc, a1, a2)                \
  407.    printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n",        \
  408.        name,                            \
  409.        (oc == NO_CHANGE ? "none" :                    \
  410.         (oc == INVISIBLE_CHANGE ? "invisible" :            \
  411.          (oc == VISIBLE_CHANGE ? "visible" :            \
  412.           (oc == STRUCTURAL_CHANGE ? "structural" : "???")))),    \
  413.        oc,                                \
  414.        (nc == NO_CHANGE ? "none" :                    \
  415.         (nc == INVISIBLE_CHANGE ? "invisible" :            \
  416.          (nc == VISIBLE_CHANGE ? "visible" :            \
  417.           (nc == STRUCTURAL_CHANGE ? "structural" : "???")))),    \
  418.        nc, desc, a1, a2)
  419. #else
  420. # define EXPLAIN(name, oc, nc, desc, a1, a2)
  421. #endif
  422.  
  423.  
  424. static widget_value *
  425. merge_widget_value (val1, val2, level)
  426.      widget_value* val1;
  427.      widget_value* val2;
  428.      int level;
  429. {
  430.   change_type change;
  431.   widget_value* merged_next;
  432.   widget_value* merged_contents;
  433.  
  434.   if (!val1)
  435.     {
  436.       if (val2)
  437.     return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
  438.       else
  439.     return NULL;
  440.     }
  441.   if (!val2)
  442.     {
  443.       free_widget_value_tree (val1);
  444.       return NULL;
  445.     }
  446.   
  447.   change = NO_CHANGE;
  448.  
  449.   if (safe_strcmp (val1->name, val2->name))
  450.     {
  451.       EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
  452.            val1->name, val2->name);
  453.       change = max (change, STRUCTURAL_CHANGE);
  454.       safe_free_str (val1->name);
  455.       val1->name = safe_strdup (val2->name);
  456.     }
  457.   if (safe_strcmp (val1->value, val2->value))
  458.     {
  459.       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
  460.            val1->value, val2->value);
  461.       change = max (change, VISIBLE_CHANGE);
  462.       safe_free_str (val1->value);
  463.       val1->value = safe_strdup (val2->value);
  464.     }
  465.   if (safe_strcmp (val1->key, val2->key))
  466.     {
  467.       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
  468.            val1->key, val2->key);
  469.       change = max (change, VISIBLE_CHANGE);
  470.       safe_free_str (val1->key);
  471.       val1->key = safe_strdup (val2->key);
  472.     }
  473.   if (val1->enabled != val2->enabled)
  474.     {
  475.       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
  476.            val1->enabled, val2->enabled);
  477.       change = max (change, VISIBLE_CHANGE);
  478.       val1->enabled = val2->enabled;
  479.     }
  480.   if (val1->selected != val2->selected)
  481.     {
  482.       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
  483.            val1->selected, val2->selected);
  484.       change = max (change, VISIBLE_CHANGE);
  485.       val1->selected = val2->selected;
  486.     }
  487.   if (val1->call_data != val2->call_data)
  488.     {
  489.       EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
  490.            val1->call_data, val2->call_data);
  491.       change = max (change, INVISIBLE_CHANGE);
  492.       val1->call_data = val2->call_data;
  493.     }
  494.  
  495.   if (level > 0)
  496.     {
  497.       merged_contents =
  498.     merge_widget_value (val1->contents, val2->contents, level - 1);
  499.       
  500.       if (val1->contents && !merged_contents)
  501.     {
  502.       EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
  503.            0, 0);
  504.       change = max (change, INVISIBLE_CHANGE);
  505.     }
  506.       else if (merged_contents && merged_contents->change != NO_CHANGE)
  507.     {
  508.       EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
  509.            0, 0);
  510.       change = max (change, INVISIBLE_CHANGE);
  511.     }
  512.       
  513.       val1->contents = merged_contents;
  514.     }
  515.  
  516.   merged_next = merge_widget_value (val1->next, val2->next, level);
  517.  
  518.   if (val1->next && !merged_next)
  519.     {
  520.       EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
  521.            0, 0);
  522.       change = max (change, STRUCTURAL_CHANGE);
  523.     }
  524.   else if (merged_next)
  525.     {
  526.       if (merged_next->change)
  527.     EXPLAIN (val1->name, change, merged_next->change, "(following change)",
  528.          0, 0);
  529.       change = max (change, merged_next->change);
  530.     }
  531.  
  532.   val1->next = merged_next;
  533.  
  534.   val1->change = change;
  535.   
  536.   if (change > NO_CHANGE && val1->toolkit_data)
  537.     {
  538.       if (val1->free_toolkit_data)
  539.     free (val1->toolkit_data);
  540.       val1->toolkit_data = NULL;
  541.     }
  542.  
  543.   return val1;
  544. }
  545.  
  546.  
  547. /* modifying the widgets */
  548. static Widget
  549. name_to_widget (instance, name)
  550.      widget_instance* instance;
  551.      char* name;
  552. {
  553.   Widget widget = NULL;
  554.  
  555.   if (!instance->widget)
  556.     return NULL;
  557.  
  558.   if (!strcmp (XtName (instance->widget), name))
  559.     widget = instance->widget;
  560.   else
  561.     {
  562.       int length = strlen (name) + 2;
  563.       char* real_name = (char *) xmalloc (length);
  564.       real_name [0] = '*';
  565.       strcpy (real_name + 1, name);
  566.       
  567.       widget = XtNameToWidget (instance->widget, real_name);
  568.  
  569.       free (real_name);
  570.     }
  571.   return widget;
  572. }
  573.  
  574. static void
  575. set_one_value (instance, val, deep_p)
  576.      widget_instance* instance;
  577.      widget_value* val;
  578.      Boolean deep_p;
  579. {
  580.   Widget widget = name_to_widget (instance, val->name);
  581.   
  582.   if (widget)
  583.     {
  584. #if defined (USE_LUCID)
  585.       if (lw_lucid_widget_p (instance->widget))
  586.     xlw_update_one_widget (instance, widget, val, deep_p);
  587. #endif
  588. #if defined (USE_MOTIF)
  589.       if (lw_motif_widget_p (instance->widget))
  590.     xm_update_one_widget (instance, widget, val, deep_p);
  591. #endif
  592. #if defined (USE_OLIT)
  593.       if (lw_olit_widget_p (instance->widget))
  594.     xol_update_one_widget (instance, widget, val, deep_p);
  595. #endif
  596. #if defined (USE_XAW)
  597.       if (lw_xaw_widget_p (instance->widget))
  598.     xaw_update_one_widget (instance, widget, val, deep_p);
  599. #endif
  600.     }
  601. }
  602.  
  603. static void
  604. update_one_widget_instance (instance, deep_p)
  605.      widget_instance* instance;
  606.      Boolean deep_p;
  607. {
  608.   widget_value *val;
  609.  
  610.   if (!instance->widget)
  611.     /* the widget was destroyed */
  612.     return;
  613.  
  614.   for (val = instance->info->val; val; val = val->next)
  615.     if (val->change != NO_CHANGE)
  616.       set_one_value (instance, val, deep_p);
  617. }
  618.  
  619. static void
  620. update_all_widget_values (info, deep_p)
  621.      widget_info* info;
  622.      Boolean deep_p;
  623. {
  624.   widget_instance* instance;
  625.   widget_value* val;
  626.  
  627.   for (instance = info->instances; instance; instance = instance->next)
  628.     update_one_widget_instance (instance, deep_p);
  629.  
  630.   for (val = info->val; val; val = val->next)
  631.     val->change = NO_CHANGE;
  632. }
  633.  
  634. void
  635. lw_modify_all_widgets (id, val, deep_p)
  636.      LWLIB_ID id;
  637.      widget_value* val;
  638.      Boolean deep_p;
  639. {
  640.   widget_info* info = get_widget_info (id, False);
  641.   widget_value* new_val;
  642.   widget_value* next_new_val;
  643.   widget_value* cur;
  644.   widget_value* prev;
  645.   widget_value* next;
  646.   int        found;
  647.  
  648.   if (!info)
  649.     return;
  650.  
  651.   for (new_val = val; new_val; new_val = new_val->next)
  652.     {
  653.       next_new_val = new_val->next;
  654.       new_val->next = NULL;
  655.       found = False;
  656.       for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
  657.     if (!strcmp (cur->name, new_val->name))
  658.       {
  659.         found = True;
  660.         next = cur->next;
  661.         cur->next = NULL;
  662.         cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
  663.         if (prev)
  664.           prev->next = cur ? cur : next;
  665.         else
  666.           info->val = cur ? cur : next;
  667.         if (cur)
  668.           cur->next = next;
  669.         break;
  670.       }
  671.       if (!found)
  672.     {
  673.       /* Could not find it, add it */
  674.       if (prev)
  675.         prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
  676.       else
  677.         info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
  678.     }
  679.       new_val->next = next_new_val;
  680.     }
  681.  
  682.   update_all_widget_values (info, deep_p);
  683. }
  684.  
  685.  
  686. /* creating the widgets */
  687.  
  688. static void
  689. initialize_widget_instance (instance)
  690.      widget_instance* instance;
  691. {
  692.   widget_value* val;
  693.  
  694.   for (val = instance->info->val; val; val = val->next)
  695.     val->change = STRUCTURAL_CHANGE;
  696.  
  697.   update_one_widget_instance (instance, True);
  698.  
  699.   for (val = instance->info->val; val; val = val->next)
  700.     val->change = NO_CHANGE;
  701. }
  702.  
  703.  
  704. static widget_creation_function
  705. find_in_table (type, table)
  706.      char* type;
  707.      widget_creation_entry* table;
  708. {
  709.   widget_creation_entry* cur;
  710.   for (cur = table; cur->type; cur++)
  711.     if (!my_strcasecmp (type, cur->type))
  712.       return cur->function;
  713.   return NULL;
  714. }
  715.  
  716. static Boolean
  717. dialog_spec_p (name)
  718.      char* name;
  719. {
  720.   /* return True if name matches [EILPQeilpq][1-9][Bb] or 
  721.      [EILPQeilpq][1-9][Bb][Rr][1-9] */
  722.   if (!name)
  723.     return False;
  724.   
  725.   switch (name [0])
  726.     {
  727.     case 'E': case 'I': case 'L': case 'P': case 'Q':
  728.     case 'e': case 'i': case 'l': case 'p': case 'q':
  729.       if (name [1] >= '0' && name [1] <= '9')
  730.     {
  731.       if (name [2] != 'B' && name [2] != 'b')
  732.         return False;
  733.       if (!name [3])
  734.         return True;
  735.       if ((name [3] == 'T' || name [3] == 't') && !name [4])
  736.         return True;
  737.       if ((name [3] == 'R' || name [3] == 'r')
  738.           && name [4] >= '0' && name [4] <= '9' && !name [5])
  739.         return True;
  740.       return False;
  741.     }
  742.       else
  743.     return False;
  744.     
  745.     default:
  746.       return False;
  747.     }
  748. }
  749.  
  750. static void
  751. instanciate_widget_instance (instance)
  752.      widget_instance* instance;
  753. {
  754.   widget_creation_function function = NULL;
  755.  
  756. #if defined (USE_LUCID)
  757.   if (!function)
  758.     function = find_in_table (instance->info->type, xlw_creation_table);
  759. #endif
  760. #if defined(USE_MOTIF)
  761.   if (!function)
  762.     function = find_in_table (instance->info->type, xm_creation_table);
  763. #endif
  764. #if defined (USE_OLIT)
  765.   if (!function)
  766.     function = find_in_table (instance->info->type, xol_creation_table);
  767. #endif
  768. #if defined (USE_XAW)
  769.   if (!function)
  770.     function = find_in_table (instance->info->type, xaw_creation_table);
  771. #endif
  772.  
  773.   if (!function)
  774.     {
  775.       if (dialog_spec_p (instance->info->type))
  776.     {
  777. #if defined (USE_LUCID)
  778.       /* not yet */
  779. #endif
  780. #if defined(USE_MOTIF)
  781.       if (!function)
  782.         function = xm_create_dialog;
  783. #endif
  784. #if defined (USE_XAW)
  785.       if (!function)
  786.         function = xaw_create_dialog;
  787. #endif
  788. #if defined (USE_OLIT)
  789.       /* not yet */
  790. #endif
  791.     }
  792.     }
  793.   
  794.   if (!function)
  795.     {
  796.       printf ("No creation function for widget type %s\n",
  797.           instance->info->type);
  798.       abort ();
  799.     }
  800.  
  801.   instance->widget = (*function) (instance);
  802.  
  803.   if (!instance->widget)
  804.     abort ();
  805.  
  806.   /*   XtRealizeWidget (instance->widget);*/
  807. }
  808.  
  809. void 
  810. lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
  811.      char* type;
  812.      char* name;
  813.      LWLIB_ID id;
  814.      widget_value* val;
  815.      lw_callback pre_activate_cb;
  816.      lw_callback selection_cb;
  817.      lw_callback post_activate_cb;
  818. {
  819.   if (!get_widget_info (id, False))
  820.     allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
  821.               post_activate_cb);
  822. }
  823.  
  824. Widget
  825. lw_get_widget (id, parent, pop_up_p)
  826.      LWLIB_ID id;
  827.      Widget parent;
  828.      Boolean pop_up_p;
  829. {
  830.   widget_instance* instance;
  831.   
  832.   instance = find_instance (id, parent, pop_up_p);
  833.   return instance ? instance->widget : NULL;
  834. }
  835.  
  836. Widget
  837. lw_make_widget (id, parent, pop_up_p)
  838.      LWLIB_ID id;
  839.      Widget parent;
  840.      Boolean pop_up_p;
  841. {
  842.   widget_instance* instance;
  843.   widget_info* info;
  844.   
  845.   instance = find_instance (id, parent, pop_up_p);
  846.   if (!instance)
  847.     {
  848.       info = get_widget_info (id, False);
  849.       if (!info)
  850.     return NULL;
  851.       instance = allocate_widget_instance (info, parent, pop_up_p);
  852.       initialize_widget_instance (instance);
  853.     }
  854.   if (!instance->widget)
  855.     abort ();
  856.   return instance->widget;
  857. }
  858.  
  859. Widget
  860. lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
  861.      char* type;
  862.      char* name;
  863.      LWLIB_ID id;
  864.      widget_value* val;
  865.      Widget parent;
  866.      Boolean pop_up_p;
  867.      lw_callback pre_activate_cb;
  868.      lw_callback selection_cb;
  869.      lw_callback post_activate_cb;
  870. {
  871.   lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
  872.               post_activate_cb);
  873.   return lw_make_widget (id, parent, pop_up_p);
  874. }
  875.           
  876.  
  877. /* destroying the widgets */
  878. static void
  879. destroy_one_instance (instance)
  880.      widget_instance* instance;
  881. {
  882.   /* Remove the destroy callback on the widget; that callback will try to
  883.      dereference the instance object (to set its widget slot to 0, since the
  884.      widget is dead.)  Since the instance is now dead, we don't have to worry
  885.      about the fact that its widget is dead too.
  886.  
  887.      This happens in the Phase2Destroy of the widget, so this callback would
  888.      not have been run until arbitrarily long after the instance was freed.
  889.    */
  890.   if (instance->widget)
  891.     XtRemoveCallback (instance->widget, XtNdestroyCallback,
  892.               mark_widget_destroyed, (XtPointer)instance);
  893.  
  894.   if (instance->widget)
  895.     {
  896.       /* The else are pretty tricky here, including the empty statement
  897.      at the end because it would be very bad to destroy a widget
  898.      twice. */
  899. #if defined (USE_LUCID)
  900.       if (lw_lucid_widget_p (instance->widget))
  901.     xlw_destroy_instance (instance);
  902.       else
  903. #endif
  904. #if defined (USE_MOTIF)
  905.       if (lw_motif_widget_p (instance->widget))
  906.     xm_destroy_instance (instance);
  907.       else
  908. #endif
  909. #if defined (USE_OLIT)
  910.       if (lw_olit_widget_p (instance->widget))
  911.     xol_destroy_instance (instance);
  912.       else
  913. #endif
  914. #if defined (USE_XAW)
  915.       if (lw_xaw_widget_p (instance->widget))
  916.     xaw_destroy_instance (instance);
  917.       else 
  918. #endif
  919.     /* do not remove the empty statement */
  920.     ;
  921.     }
  922.  
  923.   free_widget_instance (instance);
  924. }
  925.  
  926. void
  927. lw_destroy_widget (w)
  928.      Widget w;
  929. {
  930.   widget_instance* instance = get_widget_instance (w, True);
  931.   
  932.   if (instance)
  933.     {
  934.       widget_info *info = instance->info;
  935.       /* instance has already been removed from the list; free it */
  936.       destroy_one_instance (instance);
  937.       /* if there are no instances left, free the info too */
  938.       if (!info->instances)
  939.     lw_destroy_all_widgets (info->id);
  940.     }
  941. }
  942.  
  943. void
  944. lw_destroy_all_widgets (id)
  945.      LWLIB_ID id;
  946. {
  947.   widget_info* info = get_widget_info (id, True);
  948.   widget_instance* instance;
  949.   widget_instance* next;
  950.  
  951.   if (info)
  952.     {
  953.       for (instance = info->instances; instance; )
  954.     {
  955.       next = instance->next;
  956.       destroy_one_instance (instance);
  957.       instance = next;
  958.     }
  959.       free_widget_info (info);
  960.     }
  961. }
  962.  
  963. void
  964. lw_destroy_everything ()
  965. {
  966.   while (all_widget_info)
  967.     lw_destroy_all_widgets (all_widget_info->id);
  968. }
  969.  
  970. void
  971. lw_destroy_all_pop_ups ()
  972. {
  973.   widget_info* info;
  974.   widget_info* next;
  975.   widget_instance* instance;
  976.  
  977.   for (info = all_widget_info; info; info = next)
  978.     {
  979.       next = info->next;
  980.       instance = info->instances;
  981.       if (instance && instance->pop_up_p)
  982.     lw_destroy_all_widgets (info->id);
  983.     }
  984. }
  985.  
  986. #ifdef USE_MOTIF
  987. extern Widget first_child (Widget);    /* garbage */
  988. #endif
  989.  
  990. Widget
  991. lw_raise_all_pop_up_widgets ()
  992. {
  993.   widget_info* info;
  994.   widget_instance* instance;
  995.   Widget result = NULL;
  996.  
  997.   for (info = all_widget_info; info; info = info->next)
  998.     for (instance = info->instances; instance; instance = instance->next)
  999.       if (instance->pop_up_p)
  1000.     {
  1001.       Widget widget = instance->widget;
  1002.       if (widget)
  1003.         {
  1004.           if (XtIsManaged (widget)
  1005. #ifdef USE_MOTIF
  1006.           /* What a complete load of crap!!!!
  1007.              When a dialogShell is on the screen, it is not managed!
  1008.            */
  1009.           || (lw_motif_widget_p (instance->widget) &&
  1010.               XtIsManaged (first_child (widget)))
  1011. #endif
  1012.           )
  1013.         {
  1014.           if (!result)
  1015.             result = widget;
  1016.           XMapRaised (XtDisplay (widget), XtWindow (widget));
  1017.         }
  1018.         }
  1019.     }
  1020.   return result;
  1021. }
  1022.  
  1023. static void
  1024. lw_pop_all_widgets (id, up)
  1025.      LWLIB_ID id;
  1026.      Boolean up;
  1027. {
  1028.   widget_info* info = get_widget_info (id, False);
  1029.   widget_instance* instance;
  1030.  
  1031.   if (info)
  1032.     for (instance = info->instances; instance; instance = instance->next)
  1033.       if (instance->pop_up_p && instance->widget)
  1034.     {
  1035. #if defined (USE_LUCID)
  1036.       if (lw_lucid_widget_p (instance->widget))
  1037.         {
  1038.           XtRealizeWidget (instance->widget);
  1039.           xlw_pop_instance (instance, up);
  1040.         }
  1041. #endif
  1042. #if defined (USE_MOTIF)
  1043.       if (lw_motif_widget_p (instance->widget))
  1044.         {
  1045.           XtRealizeWidget (instance->widget);
  1046.           xm_pop_instance (instance, up);
  1047.         }
  1048. #endif
  1049. #if defined (USE_OLIT)
  1050.       if (lw_olit_widget_p (instance->widget))
  1051.         {
  1052.           XtRealizeWidget (instance->widget);
  1053.           xol_pop_instance (instance, up);
  1054.         }
  1055. #endif
  1056. #if defined (USE_XAW)
  1057.       if (lw_xaw_widget_p (instance->widget))
  1058.         {
  1059.           XtRealizeWidget (XtParent (instance->widget));
  1060.           XtRealizeWidget (instance->widget);
  1061.           xaw_pop_instance (instance, up);
  1062.         }
  1063. #endif
  1064.     }
  1065. }
  1066.  
  1067. void
  1068. lw_pop_up_all_widgets (id)
  1069.      LWLIB_ID id;
  1070. {
  1071.   lw_pop_all_widgets (id, True);
  1072. }
  1073.  
  1074. void
  1075. lw_pop_down_all_widgets (id)
  1076.      LWLIB_ID id;
  1077. {
  1078.   lw_pop_all_widgets (id, False);
  1079. }
  1080.  
  1081. void
  1082. lw_popup_menu (widget)
  1083.      Widget widget;
  1084. {
  1085. #if defined (USE_LUCID)
  1086.   if (lw_lucid_widget_p (widget))
  1087.     xlw_popup_menu (widget);
  1088. #endif
  1089. #if defined (USE_MOTIF)
  1090.   if (lw_motif_widget_p (widget))
  1091.     xm_popup_menu (widget);
  1092. #endif
  1093. #if defined (USE_OLIT)
  1094.   if (lw_olit_widget_p (widget))
  1095.     xol_popup_menu (widget);
  1096. #endif
  1097. #if defined (USE_XAW)
  1098.   if (lw_xaw_widget_p (widget))
  1099.     xaw_popup_menu (widget);
  1100. #endif
  1101. }
  1102.  
  1103. /* get the values back */
  1104. static Boolean
  1105. get_one_value (instance, val)
  1106.      widget_instance* instance;
  1107.      widget_value* val;
  1108. {
  1109.   Widget widget = name_to_widget (instance, val->name);
  1110.       
  1111.   if (widget)
  1112.     {
  1113. #if defined (USE_LUCID)
  1114.       if (lw_lucid_widget_p (instance->widget))
  1115.     xlw_update_one_value (instance, widget, val);
  1116. #endif
  1117. #if defined (USE_MOTIF)
  1118.       if (lw_motif_widget_p (instance->widget))
  1119.     xm_update_one_value (instance, widget, val);
  1120. #endif
  1121. #if defined (USE_OLIT)
  1122.       if (lw_olit_widget_p (instance->widget))
  1123.     xol_update_one_value (instance, widget, val);
  1124. #endif
  1125. #if defined (USE_XAW)
  1126.       if (lw_xaw_widget_p (instance->widget))
  1127.     xaw_update_one_value (instance, widget, val);
  1128. #endif
  1129.       return True;
  1130.     }
  1131.   else
  1132.     return False;
  1133. }
  1134.  
  1135. Boolean
  1136. lw_get_some_values (id, val_out)
  1137.      LWLIB_ID id;
  1138.      widget_value* val_out;
  1139. {
  1140.   widget_info* info = get_widget_info (id, False);
  1141.   widget_instance* instance;
  1142.   widget_value* val;
  1143.   Boolean result = False;
  1144.  
  1145.   if (!info)
  1146.     return False;
  1147.  
  1148.   instance = info->instances;
  1149.   if (!instance)
  1150.     return False;
  1151.  
  1152.   for (val = val_out; val; val = val->next)
  1153.     if (get_one_value (instance, val))
  1154.       result = True;
  1155.  
  1156.   return result;
  1157. }
  1158.  
  1159. widget_value*
  1160. lw_get_all_values (id)
  1161.      LWLIB_ID id;
  1162. {
  1163.   widget_info* info = get_widget_info (id, False);
  1164.   widget_value* val = info->val;
  1165.   if (lw_get_some_values (id, val))
  1166.     return val;
  1167.   else
  1168.     return NULL;
  1169. }
  1170.  
  1171. /* internal function used by the library dependent implementation to get the
  1172.    widget_value for a given widget in an instance */
  1173. widget_value*
  1174. lw_get_widget_value_for_widget (instance, w)
  1175.      widget_instance* instance;
  1176.      Widget w;
  1177. {
  1178.   char* name = XtName (w);
  1179.   widget_value* cur;
  1180.   for (cur = instance->info->val; cur; cur = cur->next)
  1181.     if (!strcmp (cur->name, name))
  1182.       return cur;
  1183.   return NULL;
  1184. }
  1185.  
  1186. /* update other instances value when one thing changed */
  1187. /* This function can be used as a an XtCallback for the widgets that get 
  1188.   modified to update other instances of the widgets.  Closure should be the
  1189.   widget_instance. */
  1190. void
  1191. lw_internal_update_other_instances (widget, closure, call_data)
  1192.      Widget widget;
  1193.      XtPointer closure;
  1194.      XtPointer call_data;
  1195. {
  1196.   /* To forbid recursive calls */
  1197.   static Boolean updating;
  1198.   
  1199.   widget_instance* instance = (widget_instance*)closure;
  1200.   char* name = XtName (widget);
  1201.   widget_info* info;
  1202.   widget_instance* cur;
  1203.   widget_value* val;
  1204.  
  1205.   /* never recurse as this could cause infinite recursions. */
  1206.   if (updating)
  1207.     return;
  1208.  
  1209.   /* protect against the widget being destroyed */
  1210.   if (XtWidgetBeingDestroyedP (widget))
  1211.     return;
  1212.  
  1213.   /* Return immediately if there are no other instances */
  1214.   info = instance->info;
  1215.   if (!info->instances->next)
  1216.     return;
  1217.  
  1218.   updating = True;
  1219.  
  1220.   for (val = info->val; val && strcmp (val->name, name); val = val->next);
  1221.  
  1222.   if (val && get_one_value (instance, val))
  1223.     for (cur = info->instances; cur; cur = cur->next)
  1224.       if (cur != instance)
  1225.     set_one_value (cur, val, True);
  1226.  
  1227.   updating = False;
  1228. }
  1229.  
  1230.  
  1231. /* get the id */
  1232.  
  1233. LWLIB_ID
  1234. lw_get_widget_id (w)
  1235.      Widget w;
  1236. {
  1237.   widget_instance* instance = get_widget_instance (w, False);
  1238.  
  1239.   return instance ? instance->info->id : 0;
  1240. }
  1241.  
  1242. /* set the keyboard focus */
  1243. void
  1244. lw_set_keyboard_focus (parent, w)
  1245.      Widget parent;
  1246.      Widget w;
  1247. {
  1248. #if defined (USE_MOTIF)
  1249.   xm_set_keyboard_focus (parent, w);
  1250. #else
  1251.   XtSetKeyboardFocus (parent, w);
  1252. #endif
  1253. }
  1254.  
  1255. /* Show busy */
  1256. static void
  1257. show_one_widget_busy (w, flag)
  1258.      Widget w;
  1259.      Boolean flag;
  1260. {
  1261.   Pixel foreground = 0;
  1262.   Pixel background = 1;
  1263.   Widget widget_to_invert = XtNameToWidget (w, "*sheet");
  1264.   if (!widget_to_invert)
  1265.     widget_to_invert = w;
  1266.   
  1267.   XtVaGetValues (widget_to_invert,
  1268.          XtNforeground, &foreground,
  1269.          XtNbackground, &background,
  1270.          0);
  1271.   XtVaSetValues (widget_to_invert,
  1272.          XtNforeground, background,
  1273.          XtNbackground, foreground,
  1274.          0);
  1275. }
  1276.  
  1277. void
  1278. lw_show_busy (w, busy)
  1279.      Widget w;
  1280.      Boolean busy;
  1281. {
  1282.   widget_instance* instance = get_widget_instance (w, False);
  1283.   widget_info* info;
  1284.   widget_instance* next;
  1285.  
  1286.   if (instance)
  1287.     {
  1288.       info = instance->info;
  1289.       if (info->busy != busy)
  1290.     {
  1291.       for (next = info->instances; next; next = next->next)
  1292.         if (next->widget)
  1293.           show_one_widget_busy (next->widget, busy);
  1294.       info->busy = busy;
  1295.     }
  1296.     }
  1297. }
  1298.